﻿using System;
using System.Collections.Generic;

namespace csharp___面向对象_sealed_and_abstract
{
    class Program
    {
        static void Main(string[] args)
        {
            // 无法创建 抽象类 的实例（无法创建接口的实例）
            //Student student = new Student(); 
            // 可以用来声明，里氏转换，父类为子类代言
            Student student = new 大学生(); 

        }
    }

    // animal 动物 ，生物
    class Animal
    {
        public virtual void Eat()
        {
            Console.WriteLine("inside animal eat");
        }
    }

    class Person : Animal
    {
        // sealed ：密封，只能写在重写的方法上，常规方法会报错
        //public sealed void Eat(){        }
        // sealed 用于修饰 重写的方法，表示子类不能再重写（override 修饰的方法）
        // 表示一个能力的退化(阉割)，在此处表示吃饭的能力在子类中退化了
        public sealed override void Eat()
        {
            Console.WriteLine("inside person eat");
        }

    }

    /// <summary>
    /// 未来的人类
    /// </summary>
    class FuturePerson : Person
    {
        //继承成员 Eat 是密封的，不能够被重写
        // public override void Eat() { }
    }

    //robot = 机器人
    // sealed 修饰类类型时，表示该 类 不能被继承，
    // 用于 已经明确知道不可能存在继承关系的类类型中,比如帮助类，管理类
    // 告诉别人（也代表未来的你）遵守你的规则的一种强制性的措施。
    sealed class Robot
    {
        /// <summary>
        /// 机器人说话的能力
        /// <br>msg = message :消息</br>
        /// </summary>
        /// <param name="msg">要表达的消息，句子</param>
        public void Say(string msg) 
        {
            Console.WriteLine($"机器人说：{msg}");
        }
    }

    // 无法从密封类 Robot 继承
    //class NewRobot : Robot {    }


    // abstract  抽象，提取本质的共通的特性
    // abstract 修饰的方法不能有实体，也就是不能有方法的具体实现
    // abstract  修饰的类类型成员（方法、属性）必须存在于 abstract 修饰的类类型种。
    // student :学生，学生本质上正在学习某一个技能中的生物个体。
    // abstract 下修饰的 student 有意义
    // abstract 对 class  ，function （方法），属性修饰，字段却不行

    // abstract 修饰的类类型中的成员不一定需要用 abstract 修饰
    abstract class Student 
    {
        public abstract string Name { get; set; }
        //sing :唱歌
        public abstract void Sing();
        /* 索引器的常规写法
        public string this[int index]
        {
            get { return "444"; }
            set { }
        }
         */

        // abstract 修饰的索引器写法
        public abstract string this[int index] { get;set; }


        public void Say() { }
    }

    // abstract 修饰的类类型如果被继承，那么 100% 实现抽象成员。
    class 大学生 : Student
    {
        string name;
        List<string> books = new List<string>();

        public override string this[int index]
        {
            get { return books[index]; }
            set { books[index] = value; }
        }

        public override string Name 
        {
            get { return name; }
            set {name=value ;}
        }

        public override void Sing()
        {
            Console.WriteLine( "大学生在唱歌");
        }
    }


}
